using Microsoft.EntityFrameworkCore;
using RiceShop.Models;

namespace RiceShop.Services
{
    /// <summary>
    /// 角色服务接口，定义了角色管理的基本操作
    /// </summary>
    public interface IRoleService
    {
        Task<IEnumerable<Role>> GetAllRolesAsync();
        Task<Role?> GetRoleByIdAsync(long id);
        Task<Role> CreateRoleAsync(Role role);
        Task<Role?> UpdateRoleAsync(long id, Role role);
        Task<bool> DeleteRoleAsync(long id);
        IEnumerable<long> GetRoleMenuPermissions(long roleId);
        void AssignMenuPermissionsToRole(AssignRoleMenuModel model);
    }

    /// <summary>
    /// 角色服务实现类，处理角色相关的业务逻辑
    /// </summary>
    public class RoleService : IRoleService
    {
        private readonly ApplicationDbContext _context;

        /// <summary>
        /// 构造函数，通过依赖注入初始化数据库上下文
        /// </summary>
        /// <param name="context">数据库上下文</param>
        public RoleService(ApplicationDbContext context)
        {
            _context = context;
        }

        /// <summary>
        /// 获取所有角色列表
        /// </summary>
        /// <returns>返回角色列表的异步任务</returns>
        public async Task<IEnumerable<Role>> GetAllRolesAsync()
        {
            return await _context.Roles.ToListAsync();
        }

        /// <summary>
        /// 根据ID获取特定角色
        /// </summary>
        /// <param name="id">角色ID</param>
        /// <returns>返回角色信息的异步任务，如果未找到则返回null</returns>
        public async Task<Role?> GetRoleByIdAsync(long id)
        {
            return await _context.Roles.FindAsync(id);
        }

        /// <summary>
        /// 创建新角色
        /// </summary>
        /// <param name="role">要创建的角色实体</param>
        /// <returns>返回创建成功的角色信息</returns>
        public async Task<Role> CreateRoleAsync(Role role)
        {
            _context.Roles.Add(role);
            await _context.SaveChangesAsync();
            return role;
        }

        /// <summary>
        /// 更新现有角色信息
        /// </summary>
        /// <param name="id">要更新的角色ID</param>
        /// <param name="role">更新后的角色信息</param>
        /// <returns>返回更新后的角色信息，如果未找到则返回null</returns>
        public async Task<Role?> UpdateRoleAsync(long id, Role role)
        {
            var existingRole = await _context.Roles.FindAsync(id);
            if (existingRole == null)
                return null;

            existingRole.roleName = role.roleName;
            existingRole.roleNormalizedName = role.roleNormalizedName;
            existingRole.roleConcurrencyStamp = role.roleConcurrencyStamp;

            await _context.SaveChangesAsync();
            return existingRole;
        }

        /// <summary>
        /// 删除指定角色
        /// </summary>
        /// <param name="id">要删除的角色ID</param>
        /// <returns>删除成功返回true，未找到返回false</returns>
        public async Task<bool> DeleteRoleAsync(long id)
        {
            var role = await _context.Roles.FindAsync(id);
            if (role == null)
                return false;

            _context.Roles.Remove(role);
            await _context.SaveChangesAsync();
            return true;
        }

        /// <summary>
        /// 获取角色的菜单权限列表
        /// </summary>
        /// <param name="roleId">角色ID</param>
        /// <returns>返回该角色拥有的菜单ID列表</returns>
        public IEnumerable<long> GetRoleMenuPermissions(long roleId)
        {
            return _context.RoleMenus
                .Where(rm => rm.roleId == roleId)
                .Select(rm => rm.menuId)
                .ToList();
        }

        /// <summary>
        /// 为角色分配菜单权限
        /// </summary>
        /// <param name="model">角色菜单权限分配模型，包含角色ID和菜单ID列表</param>
        /// <exception cref="ArgumentException">当指定的角色不存在时抛出</exception>
        /// <remarks>
        /// 该方法会：
        /// 1. 验证角色是否存在
        /// 2. 删除该角色现有的所有菜单权限
        /// 3. 添加新的菜单权限
        /// 4. 保存更改到数据库
        /// </remarks>
        public void AssignMenuPermissionsToRole(AssignRoleMenuModel model)
        {
            // 确保角色存在
            var role = _context.Roles.Find(model.RoleId);
            if (role == null)
            {
                throw new ArgumentException("指定的角色不存在", nameof(model.RoleId));
            }

            // 删除该角色的所有现有菜单权限
            _context.RoleMenus.RemoveRange(
                _context.RoleMenus.Where(rm => rm.roleId == model.RoleId)
            );

            // 添加新的菜单权限
            foreach (var menuId in model.Menus)
            {
                _context.RoleMenus.Add(new RoleMenu
                {
                    roleId = model.RoleId,
                    menuId = menuId
                });
            }

            // 保存更改到数据库
            _context.SaveChanges();
        }
    }
}
